﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using Orchard;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Localization;
using Orchard.Tokens;
using Orchard.UI.Resources;
using Rework.SocialMetadata.Models;
using Rework.SocialMetadata.Services;
using Rework.SocialMetadata.Settings;
using Rework.SocialMetadata.ViewModels;

namespace Rework.SocialMetadata.Drivers {
    public class SocialMetadataPartDriver : ContentPartDriver<SocialMetadataPart> {

        private readonly ISocialMetadataServices _socialMetadataServices;
        private readonly IWorkContextAccessor _workContextAccessor;
        private readonly ITokenizer _tokenizer;
        private const string TemplateName = "Parts/SocialMetadata";

        public SocialMetadataPartDriver(
            ISocialMetadataServices socialMetadataServices,
            IWorkContextAccessor workContextAccessor,
            ITokenizer tokenizer) {
            
            _socialMetadataServices = socialMetadataServices;
            _workContextAccessor = workContextAccessor;
            _tokenizer = tokenizer;

            T = NullLocalizer.Instance;
        }

        public Localizer T { get; set; }

        protected override string Prefix { get { return "SocialMetadata"; } }

        protected override DriverResult Display(SocialMetadataPart part, string displayType, dynamic shapeHelper) {
            if (displayType != "Detail") 
                return null;

            string patternToUse;
            var resourceManager = _workContextAccessor.GetContext().Resolve<IResourceManager>();
            
            if (part.UsePattern) {
                patternToUse = part.Pattern;
            }
            else {
                patternToUse = GetBasePattern(part);
            }
            
            if (!String.IsNullOrWhiteSpace(patternToUse)) {
                patternToUse = _tokenizer.Replace(patternToUse, BuildTokenContext(part.ContentItem));

                try {
                    // Loop over each row as each row should contain a meta pair - currently handle "Name", "Property", "Content"
                    int i = 1;
                    // Get us an array of each row
                    string[] patternArray = patternToUse.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);

                    foreach (var pattern in patternArray) {
                        // Need to split on spaces that are not in quotes
                        string[] patternComponents = pattern.Split(new string[] { "\" " }, StringSplitOptions.RemoveEmptyEntries);
                        MetaEntry metaEntry = new MetaEntry();
                        foreach (var patternComponent in patternComponents) {
                            string[] patternComponentValues = patternComponent.Split(new string[] { "=\"" }, StringSplitOptions.RemoveEmptyEntries);
                            if (patternComponentValues.Length == 2) {
                                metaEntry.AddAttribute(patternComponentValues[0].CleanLeadingEndingQuotations(), patternComponentValues[1].CleanLeadingEndingQuotations());
                            }
                        }

                        if (String.IsNullOrWhiteSpace(metaEntry.Name)) {
                            metaEntry.Name = String.Format("{0}-{1}", "meta", i);
                            i++;
                        }

                        resourceManager.SetMeta(metaEntry);
                    }
                }
                catch { }
            }
            return null;
        }

        protected override DriverResult Editor(SocialMetadataPart part, dynamic shapeHelper) {
            return ContentShape("Parts_SocialMetadata_Edit",
            () => {
                var viewModel = _socialMetadataServices.BuildSocialMetadataEditViewModel(part);

                if (String.IsNullOrWhiteSpace(viewModel.Pattern)) {
                    viewModel.Pattern = GetBasePattern(part);
                }

                return shapeHelper.EditorTemplate(
                    TemplateName: TemplateName,
                    Model: viewModel,
                    Prefix: Prefix);
            });
        }

        protected override DriverResult Editor(SocialMetadataPart part, Orchard.ContentManagement.IUpdateModel updater, dynamic shapeHelper) {
            var viewModel = new SocialMetadataEditViewModel();

            if (updater.TryUpdateModel(viewModel, Prefix, null, null)) {
                if (String.IsNullOrWhiteSpace(viewModel.Pattern)) {
                    viewModel.Pattern = GetBasePattern(part);
                }
                _socialMetadataServices.UpdateSocialMetadataPart(ref part, viewModel);
            }

            return Editor(part, shapeHelper);
        }
        
        // Helper function
        private IDictionary<string, object> BuildTokenContext(IContent item) {
            return new Dictionary<string, object> { { "Content", item } };
        }

        private static string GetBasePattern(SocialMetadataPart part) {
            var typePartSettings = part.Settings.GetModel<SocialMetadataTypePartSettings>();
            return (typePartSettings != null && !string.IsNullOrWhiteSpace(typePartSettings.Pattern))
                ? typePartSettings.Pattern
                : part.PartDefinition.Settings.GetModel<SocialMetadataPartSettings>().PatternDefault;
        }
    }

    public static class MyExtensions {
        public static string CleanLeadingEndingQuotations(this string str) {
            // Trim off any wrapping "
            if (str.StartsWith("\"")) {
                str = str.Substring(1, str.Length - 1);
            }
            if (str.EndsWith("\"")) {
                str = str.Substring(0, str.Length - 1);
            }
            return str;
        }
    }
}